<?php
namespace app\api\logic;

use app\api\cache\CarefreeCache;
use app\api\consDir\ErrorConst;
use app\api\consDir\OrderPrefixConst;
use app\api\consDir\SandConst;
use app\api\services\CarefreeInfoService;
use app\api\services\CarefreeOrderService;
use app\api\services\CartService;
use app\api\services\CouponService;
use app\api\services\MemberService;
use app\api\services\OrderService;
use app\api\services\PayService;
use app\api\services\RabbitMqService;
use app\api\services\SandService;
use app\api\services\ShopService;
use app\common\libs\Singleton;
use app\common\models\Carefree\CarefreeGoods;
use app\common\models\Carefree\CarefreeGoodsSku;
use app\common\models\Carefree\CarefreeMemberFinance;
use app\common\models\Carefree\CarefreeOrder;
use app\common\models\Carefree\CarefreeOrderGoods;
use app\common\models\CouponMember;
use app\common\models\Member\Finance;
use app\common\models\Member\Member;
use app\common\models\Order\Order;
use app\common\models\Order\OrderAddress;
use app\common\models\Order\OrderGoods;
use app\common\models\Order\OrderShop;
use app\common\models\Service\Service;
use app\common\models\Shop\Shop;
use app\common\utils\CommonUtil;
use app\common\utils\RedLock;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;

/**
 * 订单模块
 * Class MemberLogic
 * @package app\api\logic
 */
class CarefreeOrderLogic extends BaseLogic
{
    use Singleton;

    /**
     * 确认收货
     * @param  [type] $orderNo [description]
     * @return bool [type]          [description]
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function taskOrder($orderNo): bool
    {
        if ( ! RedLock::getInstance()->lock('carefreeTaskOrder_' . $this->userinfo->id, 1)) {
            CommonUtil::throwException(ErrorConst::FREQUENT_ERROR, ErrorConst::FREQUENT_ERROR_MSG);
        }
        //0待支付 1待发货 2待收货 3已收货 4已完成 5退款中 6退款成功 7取消 8超时取消 9待退货
        $order = CarefreeOrderService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        if ($order['status'] != 2) {
            CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, ErrorConst::ORDER_STATUS_ERROR_MSG);
        }
        $task = CarefreeOrderService::getInstance()->taskOrder($order);
        if (empty($task)) {
            CommonUtil::throwException(ErrorConst::SYSTEM_ERROR, ErrorConst::SYSTEM_ERROR_MSG);
        }
        // 检查会员等级升级
        try {
            \app\api\services\UserLevelService::getInstance()->checkUpgrade(
                $this->userinfo->id
            );
        } catch (\Exception $e) {
            \think\facade\Log::error($e->getMessage());
        }
        return true;
    }

    /**
     * @param $orderNo
     * @param $goodsId
     * @return array|mixed|void
     */
    public function orderExpress($orderNo, $goodsId)
    {
        $order = OrderService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }

        return OrderService::getInstance()->orderExpress($orderNo, $goodsId);
    }


    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function orderDetail($orderNo): array
    {
        $order = CarefreeOrderService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $expireTime            = strtotime($order['expireAt']) - time();
        $order['deliveryType'] = '普通快递';
        $order['expireTime']   = $expireTime > 0 ? $expireTime : 0;
        $orderAddress          = OrderService::getInstance()->getOrderAddress($orderNo);
        $supplyGoods = CarefreeOrderGoods::getInstance()->where('order_no', $order['orderNo'])->select();

        $serviceInfo = [
            'phone'  => 18938511389,
            'wechat' => 'rxx',
        ];
        return [
            'orderInfo'    => $order,
            'orderAddress' => $orderAddress,
            'serviceInfo'  => $serviceInfo,
            'supplyGoods'  => $supplyGoods,
        ];
    }

    public function delOrder($orderNo): bool
    {
        $order = CarefreeOrderService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        if ( ! in_array($order['status'], [0, 4, 6, 7, 8])) {
            CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, ErrorConst::ORDER_STATUS_ERROR_MSG);
        }
        CarefreeOrderService::getInstance()->delOrder($order);
        return true;
    }

    /**
     * 取消不需要退款
     * @param $orderNo
     * @return bool
     */
    public function cancellationOrder($orderNo): bool
    {
        $order = CarefreeOrderService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        if ($order['status'] != 0) {
            CommonUtil::throwException(ErrorConst::NO_ORDER_ERROR, ErrorConst::NO_ORDER_ERROR_MSG);
        }

        $update = [
            'status'    => 7,
            'refund_at' => date('Y-m-d H:i:s'),
        ];
        $where = [
            ['order_no', '=', $orderNo],
            ['status', '=', 0],
        ];
        CarefreeOrder::getInstance()->where($where)->update($update);
        CarefreeOrderGoods::getInstance()->where($where)->update($update);
        //退回优惠券
        $where = [
            ['id', 'in', $order['couponId']],
        ];
        CouponMember::getInstance()->where($where)->update(['status' => 0, 'update_at' => date('Y-m-d H:i:s')]);
        return true;
    }

    /**
     * 取消并退款
     * @param $orderNo
     * @return bool
     */
    public function cancelOrder($orderNo): bool
    {
        $order = OrderService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }

        if ($order['status'] != 1) {
            CommonUtil::throwException(ErrorConst::NO_ORDER_ERROR, ErrorConst::NO_ORDER_ERROR_MSG);
        }

        //30分钟
        $date = date('Y-m-d H:i:s', strtotime('-30 minutes'));
        if ($order['payAt'] < $date) {
            CommonUtil::throwException(ErrorConst::ORDER_TIME_ERROR, ErrorConst::ORDER_TIME_ERROR_MSG);
        }
        //退款逻辑
        $refund = OrderService::getInstance()->orderRefund($order);
        if ( ! $refund) {
            CommonUtil::throwException(ErrorConst::ORDER_REFUND_ERROR, ErrorConst::ORDER_REFUND_ERROR_MSG);
        }

        return true;
    }

    /**
     * @param $type
     * @param $orderType
     * @param $page
     * @param $pageSize
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function orderList($type, $page, $pageSize): array
    {
        $list = CarefreeOrderService::getInstance()->orderList($this->userinfo->id, $type, $page, $pageSize);
        return ['rows' => $list];
    }

    /**
     * @param $goodsInfo
     * @param $addressId
     * @param float|int $price
     * @param float|int $amount
     * @param string $couponId
     * @param string $userNote
     * @param array $option
     * @param int $deduction
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function createOrder($goodsInfo, $addressId, float $price = 0, float $amount = 0, string $couponId, string $userNote = '', array $option = [], float $deduction = 0): array
    {
        if ($price < 0) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        if ( ! RedLock::getInstance()->lock('createOrder:' . $this->userinfo->id, 1)) {
            CommonUtil::throwException(ErrorConst::FREQUENT_ERROR, ErrorConst::FREQUENT_ERROR_MSG);
        }
        $goodsInfo = json_decode($goodsInfo, true);
        if (empty($goodsInfo)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }

        $where = [
            ['id','=',$goodsInfo['goodsId']]
        ];
        $goods = CarefreeGoods::getInstance()->where($where)->find();
        if(empty($goods)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '商品不存在');
        }
        if($goods['status'] == 2){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '商品已下架');
        }

        if ($amount > 0) {
            $finance = MemberService::getInstance()->finance($this->userinfo->id);
            if ($amount > $finance['amount']) {
                CommonUtil::throwException(ErrorConst::NO_PRICE_ERROR, ErrorConst::NO_PRICE_ERROR_MSG);
            }
        }

        $addressInfo = MemberService::getInstance()->addressDetail($this->userinfo->id, $addressId, 2);
        if (empty($addressInfo)) {
            CommonUtil::throwException(ErrorConst::NO_ADDRESS_ERROR, ErrorConst::NO_ADDRESS_ERROR_MSG);
        }
        $sku = CarefreeGoodsSku::getInstance()->where('id',$goodsInfo['skuId'])->find();
        if(empty($sku)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '商品规格不存在');
        }

        $config = CarefreeCache::getKeyData('carefree','base');
        if(!isset($config['switch']) || $config['switch'] != 1){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '未启用无忧模块');
        }

        if($deduction > 0){
            if($config['is_can_deduction'] == 0){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '不能使用社区抵扣券抵扣');
            }
            $memberDeduction = Finance::getInstance()->where('user_id',$this->userinfo->id)->value('community_deduction');
            if($deduction > $memberDeduction){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '抵扣金不足');
            }
        }

        //分红积分
        if($config['gift_type'] == 0){
            $limit = CarefreeInfoService::getInstance()->limit($this->userinfo->id,$sku['sellPrice']*$goodsInfo['quantity']);
            if(!$limit){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '分红积分已达上限');
            }
        }

        $orderNo = getNo('WY');
        $order = CarefreeOrderService::getInstance()->createOrder($goods, $sku, $goodsInfo['quantity'], $addressInfo, $orderNo, $userNote,$this->userinfo->id, $couponId,$deduction);

        if ( ! $order) {
            CommonUtil::throwException(ErrorConst::SYSTEM_ERROR, ErrorConst::SYSTEM_ERROR_MSG);
        }

        $expireAt = date('Y-m-d H:i:s', strtotime('+5 minutes'));
        return ['orderNo' => $orderNo, 'expireAt' => $expireAt];
    }

    /**
     * 预计送到时间
     * @param  [type] $sendCity  [description]
     * @param  [type] $addressId [description]
     * @return [type]            [description]
     */
    public function estimatedDelivery($sendCity, $addressId, $startDate = null, $days = 3)
    {
        $city = '';
        if (is_numeric($sendCity)) {
            $sendCity = \think\facade\Db::table('member_shop')
                ->where('id', $sendCity)
                ->value('city');
        }
        if (empty($startDate)) {
            $startDate = new \DateTime();
        }
        $startDate->modify("+{$days} day");
        $tips = '预计' . $startDate->format('n月j日') . '后送达';
        if (is_numeric($addressId)) {
            // var_dump($sendCity);exit;
            $city = \app\common\models\Member\Address::where('id', $addressId)
                ->value('city');
        } else if (is_string($addressId)) {
            $city = $addressId;
        }
        // 同城3天，不同城5天送达
        if ($city != $sendCity) {
            $startDate->modify("+2 day");
            $tips = '预计' . $startDate->format('n月j日') . '后送达';
        }
        return $tips;
    }

    /**
     * @param $goodsInfo
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function orderPreview($goodsInfo, $couponId = ''): array
    {
        $goodsInfo = json_decode($goodsInfo, true);
        if (empty($goodsInfo)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $goods = CarefreeGoods::getInstance()->where('id',$goodsInfo['goodsId'])->find();
        $sku = CarefreeGoodsSku::getInstance()->where('id',$goodsInfo['skuId'])->find();
        $goods['sku'] = $sku;
        $goods['quantity'] = $goodsInfo['quantity'] ?? 1;
        $finance = MemberService::getInstance()->finance($this->userinfo->id);
        $carefreeFinance = CarefreeInfoService::getInstance()->finance($this->userinfo->id);
        // 订单预览新增响应“levelDiscount和couponDiscountBoth”，当 levelDiscount>0 并且 couponDiscountBoth == 0 的时候，需要前端给用户选择使用优惠券还是折扣率
        $config = CarefreeCache::getKeyData('carefree','base');
        //$deductionStatus = $config['deduction_type'] == 2 ? 0 : 1;
        return [
            'goods'              => $goods,
            'finance'            => $finance,
            'carefreeFinance'    => $carefreeFinance,
            'postage'            => 0,
            'sale'               => 0,
            //'deductionStatus'    => $deductionStatus,
            'deductionModel'     => $config['deduction_model'],
            'deduction'          => $finance['deduction'],
            'communityDeduction' => $finance['communityDeduction'],
            'deductionRate'      => $config['deduction_rate'],
            'sellPrice'          => bcmul($sku['sellPrice'],$goodsInfo['quantity'],2),
            'payPrice'           => bcmul($sku['sellPrice'],$goodsInfo['quantity'],2),
            'isCanDeduction'     => $config['is_can_deduction']
        ];
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function payOrder($orderNo, $payType, $payPassword, $paySubType): array
    {
        if ( ! RedLock::getInstance()->lock('carefreePayOrder_' . $this->userinfo->id, 3)) {
            CommonUtil::throwException(ErrorConst::FREQUENT_ERROR, ErrorConst::FREQUENT_ERROR_MSG);
        }

        if ($payType == 3) {
            $account = MemberService::getInstance()->account($this->userinfo->id);
            if (empty($account)) {
                CommonUtil::throwException(ErrorConst::NO_PAY_PASSWORD_ERROR, ErrorConst::NO_PAY_PASSWORD_ERROR_MSG);
            }

            //验证支付密码
            if ($account['payPwd'] != $payPassword) {
                CommonUtil::throwException(ErrorConst::PAY_PASSWORD_ERROR, ErrorConst::PAY_PASSWORD_ERROR_MSG);
            }
        }

        $order = CarefreeOrderService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::NO_ORDER_ERROR, ErrorConst::NO_ORDER_ERROR_MSG);
        }
        if ($order['status'] != 0) {
            CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, ErrorConst::ORDER_STATUS_ERROR_MSG);
        }

        $limit = CarefreeInfoService::getInstance()->limit($this->userinfo->id,$order['sellPrice']);
        if(!$limit){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '分红积分已达上限');
        }

        if($order['deduction'] > 0){
            $memberDeduction = Finance::getInstance()->where('user_id',$this->userinfo->id)->value('community_deduction');
            if($order['deduction'] > $memberDeduction){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '抵扣金不足');
            }
        }

        $isBalance = 0;

        CarefreeOrder::getInstance()->where('order_no', $orderNo)->update([
            'pay_type' => $payType,
        ]);
        $payInfo = PayService::getInstance()->payOrder($this->userinfo->id, $order, $payType);
        if ($payType == 3) {
            $userBalance = MemberService::getInstance()->finance($this->userinfo->id);
            if ($payInfo['pay_price'] > $userBalance['amount']) {
                CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, '余额不足');
            }
            $isBalance = 1;
        }

        $userInfo = MemberService::getInstance()->getUserInfo($this->userinfo->id);
        if ($payType == 3) {
            //余额全付
            $info = [
                'pay_status' => 3,
                'pay_no' => $payInfo['pay_no'],
                'money' => $payInfo['pay_price'],
                'trade_no' => '',
                'receipt_data' => '',
            ];
            $event["exchange"] = config('rabbitmq.order_callback_queue');
            RabbitMqService::send($event, $info);
            $pay = [];
        } elseif ($payType == 4) {
            $pay = SandLogic::getInstance()->orderCreate($this->userinfo->id, $payInfo['pay_price'], $payInfo['pay_no']);
        } elseif ($payType == 5) {
            $pay = SandLogic::getInstance()->orderCreateScan($payInfo['pay_price'], $payInfo['pay_no']);
        } else {
            $pay = PayService::getInstance()->toPay($payInfo, $userInfo, $payType, $paySubType);
        }
        return ['payInfo' => $pay, 'isBalance' => $isBalance];
    }

}
